package mop.model.task.state;

import java.util.Date;
import java.util.Map;

import mop.exception.BusinessRule2Exception;
import mop.exception.BusinessRule3Exception;
import mop.exception.RecursiveBusinessRule2Exception;
import mop.model.World;
import mop.model.task.Task;

/**
 * State class for an unfinished task
 * 
 * @author 	MOP Team 7
 */
public class Unfinished extends State 
{

	/**
	 * Constructor
	 * @param t	Task for this state
	 * @post	Task is set to given task
	 * 	|super(t)
	 */
	Unfinished(Task t) 
	{
		super(t);		
	}

	/**
	 * Constructor without exceptions !! Construction is Forced
	 * @param t Task for this state
	 * @param ignore boolean that tells us whether it's a forced construction
	 */
	public Unfinished(Task t,boolean ignore)
	{
		super(t,ignore);
	}
	
	/**
	 * Copy Constructor
	 * @param oldstate
	 * @throws RecursiveBusinessRule2Exception
	 * 		| @see rule2Parents()
	 */
	public Unfinished(State oldstate)  throws RecursiveBusinessRule2Exception
	{
		super(oldstate);
		
		Map<String,String> map = this.rule2Parents();
		if(map !=null)
		{
			throw new RecursiveBusinessRule2Exception(map);
		}
	}
	
	/***************************************************************************
	 * 						Status
	 ***************************************************************************/
	
	/**
	 * Use Case functionality
	 * Update details of task according to this state
     * @return returns false when details should not be updated
	 */
	public boolean updateDetails()
	{
		return true;
	}
	
	/**
	 * Refresh the status to comply with a correct 
	 * Unfinished -> Available/Unavailable
	 * Correct Business Rule 2 and 3
	 */
	public State refreshStatus()
	{
		try
		{
			if(this.getTask().allResourcesAvailable() && this.getTask().dependenciesAreSuccesfull() && this.getTask().getSchedule().inPeriod())
			{
					return StateFactory.createState(Available.stateName(),this.getTask());
			}
			else
			{
				return StateFactory.createState(Unavailable.stateName(),this.getTask());
			}
		}
		catch(BusinessRule2Exception e)
		{
			return StateFactory.createUncheckedState(Failed.stateName(),this.getTask());
		}
		catch(BusinessRule3Exception e)
		{
			return StateFactory.createUncheckedState(Failed.stateName(),this.getTask());
		}
	}
		
	/**
	 * Solve Exception issue f*cking bullsh*t
	 * @return
	 * @throws RecursiveBusinessRule2Exception
	 */
	public State refreshUpdateStatus() throws RecursiveBusinessRule2Exception,BusinessRule2Exception,BusinessRule3Exception
	{
			if(this.getTask().allResourcesAvailable() && this.getTask().dependenciesAreSuccesfull() && this.getTask().getSchedule().inPeriod())
			{
					return StateFactory.createUpdatedState(Available.stateName(),this);
			}
			else
			{
				return StateFactory.createUpdatedState(Unavailable.stateName(),this);
			}
	}
	
	/**
	 * Check Rule 3 for Available
	 * @return false if both conditions are not met
	 */
	public boolean rule3isMet() 
	{
		Date now = World.getTime();
		if(getTask().getSchedule().getStart().after(now))
		{
			return false;
		}
		
		if(getTask().getSchedule().getDeadline().before(now))
		{
			return false;
		}
		
		return true;
	}
	
	/***************************************************************************
	 * 						Java object interface
	 ***************************************************************************/
	
	/**
	 * Compare state with string for ease of use
	 * Unfinished == Unfinished || Available || Unavailable
	 * 
	 * @param state
	 * 		the state name to compare with
	 * 
	 * @return this.getName.equals(state)
	 */
	public boolean equals(String state)
	{
		return (this.getName().equals(state)) || (state.equals(Unavailable.stateName())) 
				|| (state.equals(Available.stateName()));
	}
	
	/**
	 * @see 	Object#toString()
	 */
	public String toString()
	{
		return "Unfinished";
	}
	
	/**
	 * return a string of the class name
	 * @return "Unfinished"
	 */
	public static String stateName()
	{
		return "Unfinished";
	}	
}
